package com.taotao.tools.core.concurrent.utils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * <p>
 * 对 CompletableFuture 的封装
 * </p>
 *
 * @author youbeiwuhuan
 * @version 1.0.0
 * @date 2023/11/13 15:11
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CompletableFutureUtils {
    /**
     *
     * 并行执行，如果有异常则抛出第一个异常
     *
     * @param runs
     * @return
     */
    public static   void runNoResult(ThreadPoolExecutor threadPool,Runnable... runs) throws Throwable {
        Callable[] callables = new Callable[runs.length];
        for (int i = 0; i < runs.length; i++) {
            final Runnable r = runs[i];
            callables[i] = new Callable() {
                @Override
                public Object call() throws Exception {
                    r.run();
                    return null;
                }
            };
        }

        runResult(threadPool,callables);
    }

    /**
     *
     * 并行执行获取结果，如果有异常则抛出第一个异常
     *
     * @param callables
     * @return
     * @param <V>
     */
    public static <V> List<V> runResult(ThreadPoolExecutor threadPool,Callable<V>... callables) throws Throwable {
        CompletableFuture<V>[] futures = new CompletableFuture[callables.length];
        for (int i = 0, len = callables.length; i < len; i++) {
            Callable<V> c = callables[i];
            futures[i] = CompletableFuture.supplyAsync(() -> {

                try {
                    return c.call();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

            },threadPool);
        }

        CompletableFuture<Void> allOfProcesses = CompletableFuture.allOf(futures);
        try {
            CompletableFuture.allOf(allOfProcesses).get();
            return Arrays.stream(futures).map(e -> {
                try {
                    return e.get();
                } catch (InterruptedException ex) {
                } catch (ExecutionException ex) {
                    // 不会到这里
                }
                // 不会到这里
                return null;
            }).collect(Collectors.toList());
        } catch (InterruptedException e) {
        } catch (ExecutionException e) {
            throw e.getCause().getCause();
        }

        return null;
    }


}
